﻿
Imports std
Imports elpmis
Imports lpmsengi.lpmsengiFunctions

Public Module lpmsengi
    Private scriptpath As String = Nothing
    Private locpath As String = Nothing
    Friend shareapp As lpmsmonitor = Nothing
    Friend globalInitial As String = Nothing
    Friend WithEvents config As configMonitor = Nothing
    Friend section As String = Nothing
    'using pointer to avoid any Cloneable change to lpmsmonitor
    Private apps As map(Of String, pointer(Of lpmsmonitor)) = Nothing
    Private defaultappscript As String = Nothing
    Private defaultapp As lpmsmonitor = Nothing
    Private initialized As [set](Of String) = Nothing

    Sub New()
        lpmshttp.register()
        lpmsstor.register()
        context.insertSharedFunction(New locstring())
        context.insertSharedFunction(New configreader2())
        context.insertSharedFunction(New configlistreader2())

        apps = New map(Of String, pointer(Of lpmsmonitor))()
        initialized = New [set](Of String)()
        AddHandler lpmsmonitor.scriptChanged2, AddressOf reinitialize
    End Sub

    Private Sub reinitialize(ByVal file As String)
        SyncLock initialized
            initialized.erase(file)
        End SyncLock
    End Sub

    Private Function scriptfile(ByVal filename As String) As String
        Return combinepath(scriptpath, filename)
    End Function

    Private Function createlpmsmonitor(ByVal script As String) As lpmsmonitor
        Return New lpmsmonitor(scriptfile(script))
    End Function

    Public Sub initial(ByVal config As configMonitor, Optional ByVal section As String = configNaming.lpmsengi.name, _
                       Optional ByVal parseDefaultApp As Boolean = True)
        lpmsengi.config = config
        copy(lpmsengi.section, section)
        scriptpath = config.parameter(section, configNaming.lpmsengi.scriptpath, _
                                      configNaming.defaultValue.lpmsserv.scriptpath)

        locpath = config.parameter(section, configNaming.lpmsengi.locpath, _
                                   configNaming.defaultValue.lpmsserv.locpath)
        initialStringsPackage(locpath)

        Dim sharescript As String = Nothing
        sharescript = config.parameter(section, configNaming.lpmsengi.share, emptyString)
        If Not isemptystring(sharescript) Then
            shareapp = createlpmsmonitor(sharescript)
            globalInitial = config.parameter(section, configNaming.lpmsengi.globalInitial, _
                                             configNaming.defaultValue.lpmsserv.globalInitial)
            lpmsmonitor.invokeglobalinitial()
        End If

        If parseDefaultApp AndAlso _
           config.getparameter(section, configNaming.lpmsengi.default, defaultappscript) Then
            defaultapp = createlpmsmonitor(defaultappscript)
        End If
    End Sub

    Private Sub initialize(ByVal app As lpmsmonitor, ByVal script As String)
        script = scriptfile(script)
        Dim needinit As Boolean = False
        SyncLock initialized
            needinit = (initialized.find(script) = initialized.end())
            If needinit Then
                initialized.insert(script)
            End If
        End SyncLock
        If needinit Then
            If Not lpmsmonitor.invokeinitial(app, config) Then
                raiseError("cannot initialize script " + script, errorHandle.errorType.warning)
            End If
        End If
    End Sub

    Friend Function lpmsengine(ByVal script As String) As lpmsmonitor
        Dim rtn As lpmsmonitor = Nothing
        lpmsengine(script, rtn)
        Return rtn
    End Function

    Friend Function lpmsengine(ByVal script As String, ByRef app As lpmsmonitor) As Boolean
        If isemptystring(script) Then
            Return False
        End If
        SyncLock apps
            Dim it As map(Of String, pointer(Of lpmsmonitor)).iterator = Nothing
            it = apps.find(script)
            If it = apps.end() Then
                it = apps.insert(script, New pointer(Of lpmsmonitor)(createlpmsmonitor(script)))
            End If

            app = +((+it).second)
        End SyncLock
        initialize(app, script)
        Return True
    End Function

    Friend Function findlpmsengine(ByVal name As String, Optional ByRef script As String = Nothing) As lpmsmonitor
        Dim rtn As lpmsmonitor = Nothing
        findlpmsengine(name, rtn, script)
        Return rtn
    End Function

    Friend Function findlpmsengine(ByVal name As String, ByRef app As lpmsmonitor, _
                                   Optional ByRef script As String = Nothing) As Boolean
        If config Is Nothing Then
            Return False
        End If
        Dim rtn As Boolean = False
        SyncLock config
            rtn = config.getparameter(section, name, script, currentContext().filters())
        End SyncLock
        If rtn Then
            Return lpmsengine(script, app)
        Else
            raiseError("cannot find lpmsapp for " + name + " for current http context.", errorHandle.errorType.warning)
            If defaultapp Is Nothing Then
                raiseError("do not have a default app in configuration.", errorHandle.errorType.warning)
                Return False
            Else
                app = defaultapp
                script = defaultappscript
                initialize(app, defaultappscript)
                Return True
            End If
        End If
    End Function

    Private Sub config_configChanged() Handles config.configChanged
        initial(config, section)
    End Sub

    Public Sub finalize()
        apps.clear()
    End Sub
End Module

Namespace configNaming
    Namespace lpmsengi
        Public Module lpmsengi
            Public Const name As String = "lpmsengi"
            Public Const scriptpath As String = "scriptpath"
            Public Const locpath As String = "locpath"
            Public Const share As String = "share"
            Public Const globalInitial As String = "globalInitial"
            Public Const [default] As String = "default"
        End Module
    End Namespace

    Namespace storoom
        Public Module storoom
            Public Const name As String = "storoom"
            Public Const storoomhost As String = "storoomhost"
            Public Const storoomport As String = "storoomport"
            Public Const storoomretrytimes As String = "storoomretrytimes"
        End Module
    End Namespace

    Namespace loc
        Public Module loc
            Public Const name As String = "loc"
            Public Const language As String = "language"
        End Module
    End Namespace

    Namespace defaultValue
        Namespace lpmsserv
            Public Module lpmsserv
                Public Const scriptpath As String = "script"
                Public Const locpath As String = "loc"
                Public Const globalInitial As String = "global_initial"
            End Module
        End Namespace

        Namespace storoom
            Public Module storoom
                Public Const storoomhost As String = "hzj-jie-8320-1"
                Public Const storoomport As Int32 = 42412
                Public Const storoomretrytimes As Int64 = storoomc.common.talkTime.client2room.retrytimes
            End Module
        End Namespace
    End Namespace
End Namespace
